package com.bjsxt.pool;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

public class TestThreadPool2 {

    public static void main(String[] args) throws Exception {

        /**
         * public ThreadPoolExecutor(int corePoolSize,
         *                           int maximumPoolSize,
         *                           long keepAliveTime,
         *                           TimeUnit unit,
         *                           BlockingQueue<Runnable> workQueue,
         *                           ThreadFactory threadFactory,
         *                           RejectedExecutionHandler handler)
         *
         * 各参数的含义和作用：
         *      1.corePoolSize：核心线程池的数量，即线程池中第一个队列可以存放的数量，
         * 当有新的任务进来时，会优先创建线程，而不是将任务放入队列。
         *      2.maximumPoolSize：最大线程池数量，当线程池中的线程数量达到corePoolSize后，
         * 会优先将任务放入队列。
         *      3.keepAliveTime：线程池中线程的空闲时间，当线程池中线程数量大于corePoolSize时，
         * 如果当前没有新的任务需要执行，那么保留keepAliveTime时间后，销毁线程。
         *      4.unit：keepAliveTime的单位，如TimeUnit.MINUTES，TimeUnit.SECONDS等。
         *      5.workQueue：任务队列，即存放任务的队列，当核心线程池中的线程数量达到上限，
         * 且任务队列没有空闲位置，那么将会创建非核心线程。
         *      6.threadFactory：线程工厂，用来创建线程，一般使用默认即可。
         *      7.handler：拒绝策略，当线程池中的线程数量达到上限，且任务队列也放不下任务时，
         * 会调用拒绝策略。
         *
         */

        //1.创建线程池对象
        //线程池中只有一个线程
        //ExecutorService pool = Executors.newSingleThreadExecutor();
        //线程池中有固定数量的线程
        ExecutorService pool = Executors.newFixedThreadPool(10);
        //线程池中有动态变化数量的线程，可以增加和减少
        //ExecutorService pool = Executors.newCachedThreadPool();
        //线程池执行定时任务
        //ExecutorService pool = Executors.newScheduledThreadPool(10);

        //2.使用线程池执行多个Callable任务
        List<Future> futureList = new ArrayList<>();
        for (int i = 1; i <= 20; i++) {

            //从 Java 8 开始，对局部变量的要求稍微放宽了一些，允许局部变量不是显式声明为 final，
            //只要它们实际上是 final（即它们的值在初始化后不会改变）即可。
            int n = i;
            //final int n = i;

            //Callable task = new MyCallable();
            //或者使用匿名内部类创建Callable对象
            Callable<Integer> task = new Callable<Integer>() {
                public Integer call() throws Exception {

                    System.out.println("任务" + n + "开始执行...");
                    Thread.sleep(1000);
                    int num = new Random().nextInt(100);
                    System.out.println("任务" + n + "执行完毕...");
                    return num;
                }
            };

            Future<Integer> future = pool.submit(task);
            futureList.add(future);
            //Integer result = future.get();      // 阻塞，等待任务执行完毕
            //System.out.println(result);
        }

        for (Future<Integer> future : futureList) {
            Integer result = future.get();
            System.out.println(result);
        }

        //3.关闭线程池
        pool.shutdown();
    }
}

/*class MyCallable implements Callable<Integer> {

    public Integer call() throws Exception {

        return new Random().nextInt(100);       // 返回一个范围在[0,100)的随机数
    }
}*/
